package com.gxp.system.service.impl;

import com.gxp.common.constant.UserConstants;
import com.gxp.common.core.domain.entity.SysRole;
import com.gxp.common.core.domain.entity.SysUser;
import com.gxp.common.core.domain.entity.ZkServiceType;
import com.gxp.common.utils.DictUtils;
import com.gxp.system.domain.*;
import com.gxp.system.domain.dto.GxpUserDto;
import com.gxp.system.domain.dto.ZkDoneExpInfoDto;
import com.gxp.system.mapper.*;
import com.gxp.system.service.ISSJService;
import com.gxp.system.service.ISysMenuService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * SpinStudioJ客户端处理实现
 */
@Service
public class SSJServiceImpl implements ISSJService {

    /**
     * 日志
     */
    private Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private SysRoleMapper roleMapper;
    @Autowired
    private ZknjServiceInstanceMapper serviceInstanceMapper;
    @Autowired
    private ZknjMethodMapper methodMapper;
    @Autowired
    private ZkNmrFileMapper nmrFileMapper;
    @Autowired
    private ZknjReqSamInfMapper reqSamInfMapper;
    @Autowired
    private ZknjRequestMapper requestMapper;
    @Autowired
    private ZknjProUserMapper proUserMapper;
    @Autowired
    private ZknjServiceApproveMapper serviceApproveMapper;
    @Autowired
    private ISysMenuService menuService;

    @Override
    public void recordAuditLogin(String username, String fail, String message) {

    }

    /**
     * 获取已完成基本实验信息
     * @param username
     * @param rolename
     * @param startTime
     * @param endTime
     * @return
     */
   @Override
    public List<ZkDoneExpInfoDto> getDoneExpInfos(String username, String rolename, String startTime, String endTime) {
        SysUser user = userMapper.selectUserByLoginName(username);
        if (user == null) {
            log.error("failed to get done exps, user == null");
            return null;
        }

        SysRole role = roleMapper.selectRoleByRolename(rolename);
        List<ZkDoneExpInfoDto> infos = new ArrayList<>();
        if (UserConstants.ROLE_REQUESTER.equals(role.getRoleId())) {
            infos = getZkDoneExpInfoDtos(username, startTime, endTime);
        }else if(UserConstants.ROLE_MANAGER.equals(role.getRoleId())) {
            //待审核实验和已完成审核实验
            ZknjServiceApprove serviceApprove = new ZknjServiceApprove();
            serviceApprove.setApproveBy(user.getLoginName());
            if (startTime != null && !startTime.isEmpty()) {
                serviceApprove.getParams().put("beginTime", startTime);
            }
            if (endTime != null && !endTime.isEmpty()) {
                serviceApprove.getParams().put("endTime", endTime);
            }
            List<ZknjServiceApprove> zknjServiceApproves = serviceApproveMapper.selectZknjServiceApproveList(serviceApprove);
            for (ZknjServiceApprove approve : zknjServiceApproves) {
                String fileName = approve.getApproveFile().getFileName();
                String expcode = approve.getExpcode();
                //根据fileName expcode获取ZkDoneExpInfoDto
                ZkDoneExpInfoDto doneExpInfoByFileAndExpcode = getDoneExpInfoByFileAndExpcode(expcode, fileName);
                if (doneExpInfoByFileAndExpcode == null) {
                    log.error("failed to get done exp, doneExpInfoByFileAndExpcode == null");
                    continue;
                }
                infos.add(doneExpInfoByFileAndExpcode);
            }

        }
        return infos;
    }

    /**
     * 根据实验编码和文件名获取已完成实验信息
     * @param expcode
     * @param fileName
     * @return
     */
    private ZkDoneExpInfoDto getDoneExpInfoByFileAndExpcode(String expcode, String fileName) {
        ZknjServiceInstance instance = serviceInstanceMapper.selectZkServiceInstanceByExpcode(expcode);
        if (instance == null) {
            log.error("failed to get done exp, instance == null");
            return null;
        }

        ZknjMethod method = methodMapper.selectZknjMethodByModId(instance.getModId());
        if (instance.getNmrFile() == null) {
            return null;
        }

        if (instance.getNmrFile().getFileName().equals(fileName)){
            return createExpInfoDto(instance, method, fileName, "1");
        } else {
            String anaNmrfileIds = instance.getAnaNmrfileIds();
            if (anaNmrfileIds != null && !anaNmrfileIds.isEmpty()) {
                for (String anaNmrfileId : anaNmrfileIds.split(",")) {
                    ZkNmrFile nmrFile = nmrFileMapper.selectZkNmrFileByFileId(Long.valueOf(anaNmrfileId));
                    if (nmrFile == null) {
                        continue;
                    }
                    if (nmrFile.getFileName().equals(fileName)){
                        return createExpInfoDto(instance, method, fileName, "2");
                    }
                }
            }
        }
        log.error("failed to get done exp, fileName not found");
        return null;
    }

    private List<ZkDoneExpInfoDto> getZkDoneExpInfoDtos(String username, String startTime, String endTime) {
        ZknjServiceInstance serviceInstance = new ZknjServiceInstance();
        serviceInstance.setProcess(Long.valueOf(DictUtils.getDictValue("auto_exp_status", "Done")));
        serviceInstance.setCreateBy(username);
        if (startTime != null && !startTime.isEmpty()) {
            serviceInstance.getParams().put("beginTime", startTime);
        }
        if (endTime != null && !endTime.isEmpty()) {
            serviceInstance.getParams().put("endTime", endTime);
        }

        List<ZknjServiceInstance> serviceInstances = serviceInstanceMapper.selectZknjServiceInstanceList(serviceInstance);
        List<ZkDoneExpInfoDto> infos = new ArrayList<>();

        for (ZknjServiceInstance instance : serviceInstances) {
            ZknjMethod method = methodMapper.selectZknjMethodByModId(instance.getModId());
            if (instance.getNmrFile() == null) {
                continue;
            }

            infos.add(createExpInfoDto(instance, method, instance.getNmrFile().getFileName(), "1"));

            String anaNmrfileIds = instance.getAnaNmrfileIds();
            if (anaNmrfileIds != null && !anaNmrfileIds.isEmpty()) {
                for (String anaNmrfileId : anaNmrfileIds.split(",")) {
                    if (anaNmrfileId == null || anaNmrfileId.isEmpty()) {
                        continue;
                    }
                    ZkNmrFile nmrFile = nmrFileMapper.selectZkNmrFileByFileId(Long.valueOf(anaNmrfileId));
                    if (nmrFile == null) {
                        continue;
                    }
                    String fileName = nmrFile.getFileName();
                    infos.add(createExpInfoDto(instance, method, fileName, "2"));
                }
            }
        }
        return infos;
    }

    @Override
    public List<ZkDoneExpInfoDto> getDoneExpInfos(List<String> expcodes) {
        List<ZkDoneExpInfoDto> infos = new ArrayList<>();
        for (String expcode : expcodes) {
            ZknjServiceInstance instance = serviceInstanceMapper.selectZkServiceInstanceByExpcode(expcode);
            if (instance == null) {
                log.error("failed to get done exp, instance == null");
                continue;
            }

            ZknjMethod method = methodMapper.selectZknjMethodByModId(instance.getModId());
            if (instance.getNmrFile() == null) {
                continue;
            }

            infos.add(createExpInfoDto(instance, method, instance.getNmrFile().getFileName(), "1"));

            String anaNmrfileIds = instance.getAnaNmrfileIds();
            if (anaNmrfileIds != null && !anaNmrfileIds.isEmpty()) {
                for (String anaNmrfileId : anaNmrfileIds.split(",")) {
                    String fileName = nmrFileMapper.selectZkNmrFileByFileId(Long.valueOf(anaNmrfileId)).getFileName();
                    infos.add(createExpInfoDto(instance, method, fileName, "2"));
                }
            }
        }
        return infos;
    }

    /**
     * 获取实验审批人
     * @param expcode
     * @return
     */
    @Override
    public List<GxpUserDto> getApprovers(String expcode) {
        ZknjServiceInstance instance = serviceInstanceMapper.selectZkServiceInstanceByExpcode(expcode);
        if (instance == null) {
            log.error("failed to get approvers, instance == null");
            return null;
        }
        List<GxpUserDto> approvers = new ArrayList<>();
        //获取projectId
        Long reqId = reqSamInfMapper.selectZknjReqSamByInfId(instance.getInfId()).getReqId();
        Long proId = requestMapper.selectZknjRequestByReqId(reqId).getProId();
        //获取审批人
        ZknjProUser proUser = new ZknjProUser();
        proUser.setPeoId(proId);
        List<ZknjProUser> zknjProUsers = proUserMapper.selectZknjProUserList(proUser);
        for (ZknjProUser proUser1 : zknjProUsers) {
            SysUser user = userMapper.selectUserById(proUser1.getUserId());
            if (user != null && user.getRoles().get(0).getRoleId().equals(UserConstants.ROLE_MANAGER)) {
                GxpUserDto dto = new GxpUserDto();
                dto.setUserId(user.getUserId());
                dto.setLoginName(user.getLoginName());
                dto.setUserName(user.getUserName());
                dto.setStatus(user.getStatus());
                dto.setRoles(user.getRoles().get(0).getRoleName());
                dto.setServiceTypes(user.getSvtypes().stream()
                        .map(ZkServiceType::getSvtypeName)
                        .collect(Collectors.toList()));
                Set<String> rolePerms = menuService.selectPermsNameByRoleId(user.getRoles().get(0).getRoleId());
                //剔除esign相关权限的其他权限
                dto.setPermissions(rolePerms.stream()
                        .filter(perm -> !perm.startsWith("esign:"))
                        .collect(Collectors.toList()));
                //获取esign相关权限
                dto.setEsignPermissions(rolePerms.stream()
                        .filter(perm -> perm.startsWith("esign:"))
                        .collect(Collectors.toList()));
                approvers.add(dto);
            }
        }
        if (approvers.isEmpty()) {
            log.error("failed to get approvers, approvers == null");
            return null;
        }
        return approvers;
    }

    private ZkDoneExpInfoDto createExpInfoDto(ZknjServiceInstance instance, ZknjMethod method, String fileName, String fileType) {
        ZkDoneExpInfoDto dto = new ZkDoneExpInfoDto();
        dto.setStartTime(instance.getStartTime());
        dto.setEndTime(instance.getEndTime());
        dto.setExpName(instance.getSample().getSamName() + "-" + method.getModName());
        dto.setExpcode(instance.getExpcode());
        dto.setInstName(instance.getInstrument().getInstName());
        dto.setHostId(instance.getInstrument().getHostId());
        dto.setCreateBy(instance.getCreateBy());
        dto.setNmrFileName(fileName);
        dto.setFileType(fileType);
        dto.setStatus(instance.getSerStatus()+"");
        return dto;
    }
}
